#include <iostream>

class Point
{
public:
    Point(int x = 0, int y = 0) : m_x(x), m_y(y) {}
    Point operator+(const Point &num1);
    friend std::ostream &operator<<(const std::ostream &os, const Point &p1);

public:
    int m_x;
    int m_y;
};
std::ostream &operator<<(std::ostream &os, const Point &p1)
{
    os << p1.m_x << "\t" << p1.m_y << std::endl;
    return os;
}
Point Point::operator+(const Point &num1)
{
    Point ret;
    ret.m_x = num1.m_x + this->m_x;
    ret.m_y = num1.m_y + this->m_y;
    return ret;
}
template <typename T>
T add(T num1, T num2)
{
    T ret = num1 + num2;
    std::cout << ret << std::endl;
    std::cout << ret.m_x << "\t" << ret.m_y << std::endl;
    return ret;
}

template <>
Point add<Point>(Point num1, Point num2)
{
    Point ret;
    ret.m_x = num1.m_x + num2.m_x;
    ret.m_y = num1.m_y + num2.m_y;
    std::cout << ret.m_x << "\t" << ret.m_y << std::endl;
    return ret;
}

int main()
{
    Point p1;
    p1.m_x = 10;
    p1.m_y = 20;
    Point p2;
    p2.m_x = 30;
    p2.m_y = 40;
    // add(1, 2);
    // add(1.2, 3);
    Point p3;
    p3 = add<Point>(p1, p2);
    Point p4;
    p4 = add(p1, p2);
}